#pragma once

#include "rcu_storage.hpp"

#include "muduo/base/noncopyable.h"
#include "rclcpp/rclcpp.hpp"

#include "interface/msg/event.hpp"
#include "interface/msg/objects.hpp"

#include <map>
#include <memory>

namespace decision::adas {

class Vehicle;
class RemoteVehicle;

class AdasApplication;

class World final : public rclcpp::Node, public muduo::noncopyable {
public:
    World();

    template <typename T>
    void addApplication(double fps = 0.1)
    {
        auto app = std::make_unique<T>(*this, fps);
        applications_[app->name()] = std::move(app);
    }

    void build();
    void start();

    void report(const interface::msg::Event& ev);
    std::shared_ptr<const Vehicle> get_host_vehicle();
    std::shared_ptr<const std::map<int64_t, std::shared_ptr<RemoteVehicle>>> get_neighbers();

private:
    void onReceiveNerghberData(const interface::msg::Objects::SharedPtr);

private:
    std::unordered_map<std::string, std::unique_ptr<AdasApplication>> applications_;

    std::shared_ptr<Vehicle> host_;
    RcuStorage<std::map<int64_t, std::shared_ptr<RemoteVehicle>>> neighbers_;

    rclcpp::Publisher<interface::msg::Event>::SharedPtr pub_;
    rclcpp::Subscription<interface::msg::Objects>::SharedPtr sub_;

    rclcpp::Logger logger_;
};

} // namespace decision::adas
